package com.itheima.es;

import com.itheima.utils.CalcUtil;
import com.itheima.utils.ElasticsearchUtil;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.metrics.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: CV大师 yuan_he_song
 * @date: 2021/7/19
 * @description: 天下风云出我辈
 */
@RestController
@RequestMapping("test")
public class TestController {

    @Autowired
    private ElasticsearchUtil searchUtil;


    private String INDEX_NAME = "test_book";

    private String INDEX_ORDER = "test_order";





    /**
     * 根据ID获取索引库当前文档信息
     */
    @GetMapping("getDoccument")
    public Map<String, Object> get(String index, String id) throws Exception{
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> doccument = searchUtil.getDoc(index, id);
        map.put("code", 0);
        map.put("status", "ok");
        map.put("message", "成功");
        map.put("data", doccument);
        return map;
    }

    /**
     * 更新文檔內容
     * @param index 索引库
     * @param object 更新内容
     * @param documentId 文檔id
     */
    @PutMapping("updateDoccument")
    public Object updateDoccument(String index, Object object, String documentId) throws Exception {
        searchUtil.updateDoc(index, object, documentId);
        return "success";
    }

    /**
     * 根据条件分页搜索
     */
    @GetMapping("getPage")
    public Object getPage(Map book) {

        // 创建搜索请求对象
        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);

        // 构建搜索内容参数设置对象,大多控制搜索内容的行为参数都可以在SearchSourceBuilder上进行设置
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 查询所有
        // sourceBuilder.query(QueryBuilders.matchAllQuery());

        // 模糊查询 ?匹配单个字符，*匹配多个字符
        //sourceBuilder.query(QueryBuilders.wildcardQuery("author", "*"+book.getAuthor()+"*"));

        // matchQuery(单个字段匹配) 会把关键词分词, 分的词去特定的字段里匹配, 有任意一个词匹配就会检索出来
        //sourceBuilder.query(QueryBuilders.matchQuery("title", pageQueryVo.getTitle()));

        // multiMatchQuery(多字段匹配) 在字段 author 和 title 中匹配传入的搜索内容
        //sourceBuilder.query(QueryBuilders.multiMatchQuery(book.getSearchKey(), "author", "title"));

        // 价格范围查询
        //sourceBuilder.query(QueryBuilders.rangeQuery("price").gte(30).lte(80));

        // 使用BoolQueryBuilder进行复合查询(会把关键词分词)
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery("author", "*" + book.getAuthor() + "*");
        //WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery("title", "*" + book.getTitle() + "*");

        // must 必须同时满足
        //boolQueryBuilder.must(queryBuilder1);
        //boolQueryBuilder.must(queryBuilder2);

        // 设置布尔查询器
        sourceBuilder.query(boolQueryBuilder);


        // 分页查询
        sourceBuilder.from(0);
        sourceBuilder.size(10);

        // 排序(id升序)
        sourceBuilder.sort("id", SortOrder.ASC);

        // 设置查询请求的超时时间：10秒没得到返回结果时就认为请求已超时
        sourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));

        // 搜索请求对象设置请求体
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = searchUtil.search(searchRequest);

        // 总记录数
        SearchHits searchHits = searchResponse.getHits();
        long length = searchHits.getTotalHits().value;
        System.err.println("总记录数: " + length);

        for (SearchHit searchHit : searchHits) {
            String sourceAsString = searchHit.getSourceAsString();
            System.out.println(sourceAsString);
        }

        return "success";
    }


    /**
     * 求平均值/最大值/最小值
     */
    @PostMapping("avg")
    public Object getAvg(){
        SearchRequest searchRequest = new SearchRequest(INDEX_ORDER);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // maxAmount 自定义的名称 totalAmount:文档字段
        MaxAggregationBuilder maxAmount = AggregationBuilders.max("maxAmount").field("totalAmount");
        MinAggregationBuilder minAmount = AggregationBuilders.min("minAmount").field("totalAmount");
        AvgAggregationBuilder avgAmount = AggregationBuilders.avg("avgAmount").field("totalAmount");
        SumAggregationBuilder sumAmount = AggregationBuilders.sum("sumAmount").field("totalAmount");

        // 添加聚合查询参数
        sourceBuilder.aggregation(maxAmount);
        sourceBuilder.aggregation(minAmount);
        sourceBuilder.aggregation(avgAmount);
        sourceBuilder.aggregation(sumAmount);

        searchRequest.source(sourceBuilder);

        SearchResponse response = searchUtil.search(searchRequest);
        Aggregations aggregations = response.getAggregations();

        // 最大值
        Max max = aggregations.get("maxAmount");
        double maxValue = max.getValue();
        String format3 = CalcUtil.format(new BigDecimal(maxValue));
        System.out.println("最大值: " + format3);

        // 最小值
        Min min = aggregations.get("minAmount");
        double minValue = min.getValue();
        String format2 = CalcUtil.format(new BigDecimal(minValue));
        System.out.println("最小值: " + format2);

        // 平均值
        Avg avg = aggregations.get("avgAmount");
        double avgValue = avg.getValue();
        String format1 = CalcUtil.format(new BigDecimal(avgValue));
        System.out.println("平均值: " + format1);

        // 求总和
        Sum sum = aggregations.get("sumAmount");
        double sumValue = sum.getValue();
        String format = CalcUtil.format(new BigDecimal(sumValue));

        System.out.println("总和: " + format);

        return "success";
    }

}
